package org.iweb.init;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;

import org.iweb.init.classloader.IWebClassLoader;
import org.iweb.init.scanner.AnnotationScanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings({"rawtypes","unchecked"})
public class RegisterFactory implements IRegisterFactory{

	private Map<String, AbstractRegister> registers;

	private static RegisterFactory instance;
	
	private static MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
	
	protected final static Logger log = LoggerFactory
			.getLogger(RegisterFactory.class);

	public RegisterFactory() {
	}

	public static RegisterFactory getInstance() {
		if (instance == null) {
			instance = new RegisterFactory();
		}
		return instance;
	}

	public Map<String, AbstractRegister> getRegisters() {
		if (registers == null)
			registers = new HashMap<String, AbstractRegister>();
		return registers;
	}

	public AbstractRegister getRegisterByName(String name) {
		return getRegisters().get(name);
	}

	public void reload(IWebClassLoader classLoader) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		try {

			getRegisters().clear();

			AnnotationScanner annotationScanner=(AnnotationScanner)classLoader.loadClass(AnnotationScanner.class.getName()).newInstance();
			
			annotationScanner.setClassLoader(classLoader);
			annotationScanner.findAnnotation();
			
//			AnnotationScanner annotationScanner = new AnnotationScanner(classLoader);

			List<Class> annotated = annotationScanner
					.getListByAnnotation(Register.class);

			for (Class c : annotated) {

				try {

					Register ann = (Register) c.getAnnotation(Register.class);

					AbstractRegister abr=(AbstractRegister) c.newInstance();
					
					ObjectName oname=new ObjectName("org.iweb.jmx:type="+abr.getClass().getName());
					if(mbs.isRegistered(oname)){
						mbs.unregisterMBean(oname);
					}
					
					mbs.registerMBean(abr,oname);
					
					instance.getRegisters().put(ann.name(),abr);

				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InstanceAlreadyExistsException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (MBeanRegistrationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (NotCompliantMBeanException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (MalformedObjectNameException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InstanceNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			for (AbstractRegister as : instance.getRegisters().values()) {
				as.clear();
				as.populate(annotationScanner);
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}

	@Override
	public void init(ClassLoader classLoader) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		getInstance().reload((IWebClassLoader)classLoader);		
	}
}
